from google.appengine.ext import db
from google.appengine.api import users
import demjson
import types
import re

class EntitySerializer(object):
	def __init__(self, recursive=False):
		self.__recursive = recursive

	def __build_dict(self, entity):
		result = {}
		result["key"] = str(entity.key())
		base = db.class_for_kind(entity.kind())	
		for name, property in base._properties.iteritems():
			ty = type(property)
			if ty is db.StringProperty or \
				ty is db.BooleanProperty or \
				ty is db.IntegerProperty or \
				ty is db.FloatProperty:
				result[name] = getattr(entity, name)
			elif ty is db.TextProperty or \
				ty is db.BlobProperty or \
				ty is db.CategoryProperty or \
				ty is db.LinkProperty or \
				ty is db.EmailProperty or \
				ty is db.IMProperty or \
				ty is db.DateTimeProperty or \
				ty is db.DateProperty or \
				ty is db.TimeProperty or \
				ty is db.PhoneNumberProperty or \
				ty is db.PostalAddressProperty:
				result[name] = None
				value = getattr(entity, name)
				if value != None:
					result[name] = str(value)
			elif ty is db.RatingProperty:
				result[name] = None
				rating = getattr(entity, name)
				if rating != None:
					result[name] = long(rating)
			elif ty is db.GeoPtProperty:
				result[name] = None
				point = getattr(entity, name)
				if point != None:
					result[name] = {
						"lat": point.lat,
						"lon": point.lon
					}
			elif ty is db.UserProperty:
				result[name] = None
				user = getattr(entity, name)
				if user != None:
					result[name] = {
						"nickname": user.nickname(),
						"email": user.email()
					}
			elif ty is db.ListProperty or \
				ty is db.StringListProperty:
				result[name] = []
				array = getattr(entity, name)
				if array:
					pty = property.item_type
					if pty is db.Key or \
						pty is db.Blob or \
						pty is db.Text or \
						pty is db.Category or \
						pty is db.Link or \
						pty is db.Email or \
						pty is db.IM or \
						pty is db.PhoneNumber or \
						pty is db.PostalAddress:
						result[name] = [str(item) for item in array]
					elif pty is db.Rating:
						result[name] = [long(item) for item in array]
					elif pty is db.GeoPt:
						result[name] = [{ "lat": item.lat, "lon": item.lon } for item in array]
					elif pty is users.User:
						result[name] = [{ "nickname": item.nickname(), "email": item.email() } for item in array]
					else:
						result[name] = array
			elif ty is db.ReferenceProperty or \
				ty is db.SelfReferenceProperty:
				result[name] = None
				result["%s_key" % name] = None
				reference = getattr(entity, name)
				if reference:
					result["%s_key" % name] = str(reference.key())
					if self.__recursive == True:
						result[name] = self.__build_dict(reference) 
				
		return result
	
	def serialize(self, entity):
		dict = self.__build_dict(entity)
		return demjson.encode(dict) 

def serialize_entity(entity, recursive=False):
	return EntitySerializer(recursive).serialize(entity)
